//////////////////////////////////////////////////////////////////////
////                                                              ////
////  CFAddressDecoder.v                                          ////
////                                                              ////
////                                                              ////
////  This file is part of the "Pico E12" project                 ////
////  http://www.picocomputing.com                                ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2005, Picocomputing, Inc.                      ////
//// http://www.picocomputing.com/                                ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
////////////////////////////////////////////////////////////////////JF

//Address Latches and Address Extension Decoder
`include "PicoDefines.v"

`timescale 10ns / 1ns
									
module CFAddressDecoder(CFClock, CardEnabled, A, REG, OE, WE, IORD, IOWR, INPACK, IOIS16, IORead, IOWrite, AttribRead, AttribWrite,
                       	MemAddress, IOAddress, DataIn, DataOut);

input CFClock;                                                                      //200 MHz Free Running Oscillator
input CardEnabled;                                                                  //CE1 or CE2 is low
input [10:0]A;                                                                      //Raw Address bus from the PCMCIA interface
input REG;                                                                          //Attribute / IO Transfer Signal
input OE;                                                                           //Memory Read
input WE;                                                                           //Memory Write
input IORD;                                                                         //I/O Read
input IOWR;                                                                         //I/O Write
output INPACK;                                                                      //Input Acknowledge (Asserted when a valid IO address is detected)   
output IOIS16;
input IOWrite;                                                                      //IO Write to Card Signal
input IORead;                                                                       //IO Read from Card Signal
input AttribRead;                                                                   //Attribute Read from Card Signal
input AttribWrite;                                                                  //Attribute Write to Card Signal

output [31:0]MemAddress;                                                            //Raw Address bus from the PCMCIA interface
output [`PCMCIA_ADR_LINES-1:0]IOAddress;                                            //Address bus for the IO Interface
input [15:0]DataIn;                                                                 //Data to host bus
output [15:0]DataOut;                                                               //Data from host bus
																             
reg [10:0]WindowAddress;                                                            //Raw Window Address [LSBs]
reg [15:0]AddressExtension1;                                                        //Address Extension #1 (Used in memory only)
reg [4:0]AddressExtension2;                                                         //Address Extension #2 (Used in memory only)

wire IOWriteAddressExtension1;                                                      //Enable Signals for Address Extension Writes
wire IOWriteAddressExtension2;
wire AttribWriteAddressExtension1;
wire AttribWriteAddressExtension2;
wire AttribWriteAddressExtension3;

wire [15:0]IODataOutAddressExtension1;                                              //Data Busses for Address Extension Reads
wire [15:0]IODataOutAddressExtension2;
wire [7:0]AttribDataOutAddressExtension1;
wire [7:0]AttribDataOutAddressExtension2;
wire [7:0]AttribDataOutAddressExtension3;

wire AddressExtensionWrite;

wire AddressLatch;

//Addresses are latched after CE goes low and a transfer has not yet started
AddressLatchDecoder AddressLatchDecoder(.CFClock(CFClock), .CardEnabled(CardEnabled), 
                                        .OE(OE), .WE(WE), .IORD(IORD), .IOWR(IOWR), .AddressLatch(AddressLatch));

always @(AddressLatch or WindowAddress[10:0] or A[10:0])
	if (AddressLatch) WindowAddress[10:0] <= A[10:0];

//-----------Write Enable Signals---------------//
assign IOWriteAddressExtension1 = ((IOAddress[2]) && (IOAddress[`PCMCIA_ADR_LINES-1:1] == `IO_ADDRESS_EXTENSION_1) && (IOWrite));       //IOAddress[3] is used as a select between the Parallel Port and Everything else in IO
assign IOWriteAddressExtension2 = ((IOAddress[2]) && (IOAddress[`PCMCIA_ADR_LINES-1:1] == `IO_ADDRESS_EXTENSION_2) && (IOWrite));
assign AttribWriteAddressExtension1 = (WindowAddress[10:1] == `ATTRIB_ADDRESS_EXTENSION_1) && AttribWrite;
assign AttribWriteAddressExtension2 = (WindowAddress[10:1] == `ATTRIB_ADDRESS_EXTENSION_2) && AttribWrite;
assign AttribWriteAddressExtension3 = (WindowAddress[10:1] == `ATTRIB_ADDRESS_EXTENSION_3) && AttribWrite;

//------Asynchronous Write Clock Generation-----//
wire AddressExtensionWritePreDelay = (IOWriteAddressExtension1 | IOWriteAddressExtension2 | AttribWriteAddressExtension1 | AttribWriteAddressExtension2 | AttribWriteAddressExtension3);
Delay AddressExtensionWriteDelay(.Clock(CFClock), .In(AddressExtensionWritePreDelay), .Out(AddressExtensionWrite));

always @(posedge AddressExtensionWrite) begin                             //IO Address Extension
	if (IOWriteAddressExtension1 || AttribWriteAddressExtension1) AddressExtension1[7:0] <= DataIn[7:0];
end

always @(posedge AddressExtensionWrite) begin
	if (IOWriteAddressExtension1 || AttribWriteAddressExtension2) AddressExtension1[15:8] <= DataIn[15:8]; 
end

always @(posedge AddressExtensionWrite) begin
	if (IOWriteAddressExtension2 || AttribWriteAddressExtension3) AddressExtension2[4:0] <= DataIn[4:0];
end

//-----------Address Extension Read-------------//
assign IODataOutAddressExtension1[15:0] = ((IORead) && (IOAddress[2]) && (IOAddress[`PCMCIA_ADR_LINES-1:1] == `IO_ADDRESS_EXTENSION_1))?(AddressExtension1[15:0]) : 16'b0;
assign IODataOutAddressExtension2[4:0] = ((IORead) && (IOAddress[2]) && (IOAddress[`PCMCIA_ADR_LINES-1:1] == `IO_ADDRESS_EXTENSION_2))?(AddressExtension2[4:0]) : 5'b0;
assign IODataOutAddressExtension2[15:5] = 11'b0;

assign AttribDataOutAddressExtension1[7:0] = (AttribRead && (A[10:1] == `ATTRIB_ADDRESS_EXTENSION_1))?(AddressExtension1[7:0]) : 8'b0;
assign AttribDataOutAddressExtension2[7:0] = (AttribRead && (A[10:1] == `ATTRIB_ADDRESS_EXTENSION_2))?(AddressExtension1[15:8]) : 8'b0;
assign AttribDataOutAddressExtension3[4:0] = (AttribRead && (A[10:1] == `ATTRIB_ADDRESS_EXTENSION_3))?(AddressExtension2[4:0]) : 5'b0;
assign AttribDataOutAddressExtension3[7:5] = 3'b0;


assign DataOut[7:0] = (IODataOutAddressExtension1[7:0] | IODataOutAddressExtension2[7:0] | AttribDataOutAddressExtension1[7:0] | AttribDataOutAddressExtension2[7:0] | AttribDataOutAddressExtension3[7:0]);
assign DataOut[15:8] = (IODataOutAddressExtension1[15:8] | IODataOutAddressExtension2[15:8] | AttribDataOutAddressExtension1[7:0] | AttribDataOutAddressExtension2[7:0] | AttribDataOutAddressExtension3[7:0]);

//-----------Memory Address Bus-----------------//
assign MemAddress[10:0] = WindowAddress[10:0];
assign MemAddress[26:11] = AddressExtension1[15:0]; 
assign MemAddress[31:27] = AddressExtension2[4:0];

//-------------IO Address Bus-------------------//
assign IOAddress[`PCMCIA_ADR_LINES-1:0] = WindowAddress[`PCMCIA_ADR_LINES-1:0];                                        //The IOAddress is now calculated in each peripheral on the fly.

assign INPACK = ~(IORead);                                                                                             //This turns on the Input Buffers on the host side
																												  
assign IOIS16 = ~((A[2]) && (~REG) && (OE) && (WE));                                                                   //Enable 16 Bit mode for everything except the parallel port 

endmodule